<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="824.47">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #bf0000}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #000000}
span.s1 {color: #0000ff}
span.s2 {color: #3468c9}
span.s3 {color: #0000bf}
span.s4 {color: #000000}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><b>SOMRd<span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>Map an input using a Self-Organising Map</b></p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-tab-span">	</span><b>SOMRd.kr(bufnum, inputdata, netsize, numdims, gate)</b></p>
<p class="p2"><br></p>
<p class="p3">Once you have created a <i>self-organising map</i> using <a href="SOMTrain.html"><span class="s1">SOMTrain</span></a>, you can query it using SOMRd. This UGen takes an input vector (i.e. multichannel input) and outputs the co-ordinate of the best-matching node in the SOM, i.e. the node which is closest to the input vector (using Euclidean distance). It can run at control- or audio-rate.</p>
<p class="p2"><br></p>
<p class="p3"><span class="Apple-converted-space"> </span>- <b>bufnum</b><span class="Apple-tab-span">	</span>- A reference to the buffer containing the SOM.</p>
<p class="p3"><span class="Apple-converted-space"> </span>- <b>inputdata</b><span class="Apple-tab-span">	</span>- An <a href="SC://Array"><span class="s2">Array</span></a> of the input signals for the net to map.</p>
<p class="p3"><span class="Apple-converted-space"> </span>- <b>netsize</b><span class="Apple-tab-span">	</span>- The size of the neural net along one dimension. Must match what you trained it with.</p>
<p class="p3"><span class="Apple-converted-space"> </span>- <b>numdims</b> - The dimensionality of the neural net. Choose from 1, 2, 3, or 4. Must match what you trained it with.</p>
<p class="p3"><span class="Apple-converted-space"> </span>- <b>gate</b> <span class="Apple-tab-span">	</span>-<span class="Apple-converted-space">  </span>A simple on-or-off control. When off (gate&lt;=0) the incoming data is ignored (output stays constant).</p>
<p class="p2"><br></p>
<p class="p3">For some applications you might want to retrieve the best-matching <i>template vector</i>, i.e. the spatial location of the best-matching node, rather than just its index in the net. You can use <b>SOMRd.coordsToBufIndex(coords, netsize)</b> to find which Buffer frame contains that vector, and then use <a href="SC://BufRd"><span class="s1">BufRd</span></a> to pull the vector out. See examples...</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
<p class="p3"><b>Examples</b></p>
<p class="p2"><br></p>
<p class="p3">Here we'll assume you have a SOM trained as in the example from the <a href="SOMTrain.html"><span class="s1">SOMTrain</span></a> helpfile, i.e. it's stored in variable ~som, with ~numnodes nodes, and a 1D net trained on 2D input data.</p>
<p class="p2"><br></p>
<p class="p4">// This simple example takes mouse X and Y coords onscreen and prints the co-ordinate of the nearest node.</p>
<p class="p4">// Try drawing a big sinewave across the screen, like the one plotted in the SOMTrain helpfile.</p>
<p class="p3">(</p>
<p class="p5">x = {</p>
<p class="p5"><span class="s3">var</span> coords;</p>
<p class="p5">coords = <span class="s3">SOMRd</span>.kr(~som, [<span class="s3">MouseX</span>.kr(0, <span class="s4">2</span>), <span class="s3">MouseY</span>.kr(1, -1)], ~numnodes, 1);</p>
<p class="p5">coords.poll(4);</p>
<p class="p5">}.play</p>
<p class="p3">)</p>
<p class="p2"><br></p>
<p class="p4">// This is the same as above but then retrieves the "template vector" from the SOM and uses it for pitch/cutoff of a tone.</p>
<p class="p4">// Top of screen = hi cutoff, bottom of screen = lo cutoff. Left = lo pitch, right = hi pitch.</p>
<p class="p4">// Notice how the SOM mapping constrains what is possible, and you get the best resolution by following the sine curve.</p>
<p class="p3">(</p>
<p class="p5">x = {</p>
<p class="p5"><span class="s3">var</span> coords, index, vec;</p>
<p class="p5">coords = <span class="s3">SOMRd</span>.kr(~som, [<span class="s3">MouseX</span>.kr(0, 2), <span class="s3">MouseY</span>.kr(1, -1)], ~numnodes, 1);</p>
<p class="p5">coords.poll(4);</p>
<p class="p5">index = <span class="s3">SOMRd</span>.coordsToBufIndex(coords, ~numnodes);</p>
<p class="p4"><span class="s4">vec = </span><span class="s3">BufRd</span><span class="s4">.kr(2, ~som, index); </span>// "vec" is of range [0 to 2, -1 to 1]</p>
<p class="p5"><span class="s3">MoogFF</span>.ar(<span class="s3">Saw</span>.ar(vec[0].linexp(0, 2, 80, 400)), vec[1].linexp(-1, 1, 300, 15000), mul: 0.1).dup;</p>
<p class="p5">}.play</p>
<p class="p3">)</p>
<p class="p2"><br></p>
<p class="p4">// Audio-rate example, a slightly weird one.</p>
<p class="p4">// Essentially this takes a "query" wave and looks it up in the map, therefore coercing it to a strange sort-of-sine-like shape.</p>
<p class="p4">// Try this on the internal server and scope the results.</p>
<p class="p3">(</p>
<p class="p5">x = {</p>
<p class="p5"><span class="s3">var</span> freq, query, coords, index, vec;</p>
<p class="p5">freq = <span class="s3">MouseX</span>.kr(100, 400, 1);</p>
<p class="p3"><span class="s4">query = </span><span class="s3">LFTri</span>.ar(freq).range(1, -1);</p>
<p class="p5">coords = <span class="s3">SOMRd</span>.ar(~som, [<span class="s3">Saw</span>.ar(freq).range(0, 2), <span class="s3">query</span>], ~numnodes, 1);</p>
<p class="p5">index = <span class="s3">SOMRd</span>.coordsToBufIndex(coords, ~numnodes);</p>
<p class="p5">vec = <span class="s3">BufRd</span>.ar(2, ~som, index);</p>
<p class="p4"><span class="s4">[query, vec[1]] * 0.1; </span>// Output the vertical position from the map</p>
<p class="p5">}.play</p>
<p class="p3">)</p>
</body>
</html>
